<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>apply,call,bind</title>
</head>
<style>
  span {
    color: red;
  }
</style>
<body>
  <div>apply,call,bind用法，call()、apply()、bind() 都是用来重定义 this 这个对象的！</div>
  <div>函数里的this指向的是全局<span>windows</span></div>
  <div>apply,call,bind三个参数第一个参数都是指定绑定的this对象， 第二个参数不同</div>
  <ul>
    <li>apply 第二个参数是一个<span>数组</span></li>
    <li>call 第二个参数可以是一个<span>字符串</span></li>
    <li>bind 除了返回是<span>函数</span>以外，它 的参数和 call 一样</li>
  </ul>
  <h4>apply</h4>
  <div></div>
  <h4>call</h4>
  <h4>bind</h4>

  <script>
    // 1. 比较this 指向
    var name = "小王", age=17;
    var obj = {
      name: "小张",
      objAge: this.age,
      myFun: function() {
        console.log(this.name + "年龄" + this.age)
        console.log(this) // 这个this 指向的是 obj 这个对象
      }
    }
    obj.objAge; // 17
    obj.myFun();  // 小张年龄undefined

    //2 
    var fav = "盲僧";
    function shows() {
      console.log(this.fav)  // 盲僧 

      console.log(this) // this 指向windows =============
    }
    shows()

    // 3. call()、apply()、bind() 都是用来定义 this 指向
    var db = {
      name: "德玛",
      age: 99
    }

    obj.myFun.call(db) //德玛年龄99
    obj.myFun.apply(db) // 德玛年龄99
    obj.myFun.bind(db)(); // 德玛年龄99 // bind是绑定这个参数但是需要调用 ========

    // 总结
    // 以上出了 bind 方法后面多了个 () 外 ，结果返回都一致！
    // 由此得出结论，bind 返回的是一个新的函数，你必须调用它才会被执行。

    //4 传参方式区别
    var name = "小王", age=17;
    var obj5 = {
      name: "小张",
      objAge: this.age,
      myFun: function(fm, t) {
        console.log(this.name + "年龄" + this.age, "来自" + fm + ",去往" + t)
        console.log(this) // 这个this 指向的是 obj 这个对象
      }
    }
    console.log("=================分隔符===============")
    obj5.objAge; // 17
    obj5.myFun();  

  
    var db = {
      name: "小熊",
      age: 99
    }

    obj5.myFun.call(db, "成都", "上海");     // 小熊年龄99 来自成都去往上海
    obj5.myFun.apply(db, ["成都", "上海"]);  // 小熊年龄99 来自成都去往上海
    obj5.myFun.bind(db, "成都", "上海")();   // 小熊年龄99 来自成都去往上海
    obj5.myFun.bind(db,[ "成都", "上海"])(); // 小熊年龄99 来自成都,上海,去往undefined  ！！！！！！！！！！！


    // 总结
    // call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象，第二个参数差别就来了：
    // call 的参数是直接放进去的，第二第三第 n 个参数全都用逗号分隔，直接放到后面 obj.myFun.call(db,'成都', ... ,'string' )。
    // apply 的所有参数都必须放在一个数组里面传进去 obj.myFun.apply(db,['成都', ..., 'string' ])。
    // bind 除了返回是函数以外，它 的参数和 call 一样。
    // 当然，三者的参数不限定是 string 类型，允许是各种类型，包括函数 、 object 等等！

  </script>
</body>
</html>